import React, { useCallback, useEffect, useState } from "react";
import styles from "./styles.module.scss";
import cn from "classnames";
import { Spin, App } from "antd";
import { LoadingOutlined } from '@ant-design/icons';
import { LibAppView } from "../../lib";
import { useService } from "../../lib/Service";
import { useValidatedForm } from "../../lib/Validation";

interface IInputProps {
    className?: string;
    label: string;
    placeholder: string;
    type: string;
    name: string;
    maxLength?: number;
    onChange?: (e: any) => void;
    onBlur?: (e: any) => void;
    children?: React.ReactNode;
    disabled?: boolean;
}

export const Input = (props: IInputProps) => {
    return (<label className={cn(styles.inputBox, props.className)}>
        <span>{props.label}</span>
        <div>
            <input
                maxLength={props.maxLength}
                type={props.type}
                placeholder={props.placeholder || ""}
                onBlur={props.onBlur}
                disabled={props.disabled}
                onChange={(event) => typeof props.onChange === "function" && props.onChange(event.target.value)}
            />
            {props.children}
        </div>
    </label>);
};

export const SmsOtp = (props: IInputProps) => {
    const serviceApi = useService();
    const [ disCount, setDisCount ] = useState(60);
    const [ loading, setLoading ] = useState(false);
    const [ showDiscount, setShowDiscount ] = useState(false);
    const validateForm = useValidatedForm<{'vd-mobile': string, 'vd-verifyCode': string}>();
    const { message } = App.useApp();
    const startDiscount = useCallback(() => {
        let timeDiscount = 60;
        setLoading(false);
        setShowDiscount(true);
        setDisCount(timeDiscount);
        const timer = setInterval(() => {
            if (timeDiscount > 0) {
                timeDiscount -= 1;
                setDisCount(timeDiscount);
            } else {
                setShowDiscount(false);
                clearInterval(timer);
            }
        }, 1000);
    }, []);
    const onSendClick = useCallback(() => {
        setLoading(true);
        serviceApi.send({
            endPoint: "login.sendSMS",
            header: {
                captcha_code: validateForm.getValue("vd-verifyCode") || ""
            },
            variables: {
                phoneNumber: validateForm.getValue("vd-mobile") || ""
            }
        }).then(() => {
            startDiscount();
        }).catch((error) => {
            message.error(error.message || "未知错误");
            setLoading(false);
        });
    }, []);
    return (<Input {...props} className={styles.inputBoxSMSOTP}>
        <button disabled={loading || showDiscount} type="button" onClick={onSendClick}>
            { !loading && <span>{showDiscount ? `已发送(${disCount})秒` : "发送验证码"}</span> }
            { loading && <span><Spin indicator={<LoadingOutlined />}/><span>正在发送</span></span> }
        </button>
        {props.children}
    </Input>);
}

export const VerifyCode = LibAppView.withService<IInputProps>()((props) => {
    const [ imgUrl ] = useState(() => props.withServiceApi.getUrl("login.captchaGenerate") as any);
    const [ verifyImg, setVerifyImg ] = useState<string>();
    const [ canvas ] = useState(() => document.createElement("canvas"));
    const [ canvasContext ] = useState(() => canvas.getContext("2d"));
    const updateImg = useCallback(() => {
        const timestamp = new Date().getTime();
        props.withServiceApi.send({
            endPoint: "login.captchaGenerate",
            uri: {
                timestamp
            },
            header: {
                "Content-Type": "image/jpeg"
            }
        }).then((resp: any) => {
            const fileReader = new FileReader();
            fileReader.onload = () => {
                setVerifyImg(fileReader.result as string)
            };
            fileReader.onerror = () => {
                setTimeout(() => updateImg(), 1000);
            }
            fileReader.readAsDataURL(resp);
        }).catch((err) => {
            console.error(err);
            setTimeout(() => updateImg(), 2000);
        });
    },[imgUrl]);
    useEffect(()=> {
        canvas.setAttribute("style", "position: absolute;left:0;top:0;z-index: -2");
        document.body.appendChild(canvas);
        updateImg();
        return () => {
            document.body.removeChild(canvas);
        };
    }, []);
    return (<Input {...props} className={styles.inputBoxVerifyCode}>
        <>
            { verifyImg && <img
                className={styles.verifyCode}
                src={verifyImg}
                onClick={() => {
                    setVerifyImg(undefined);
                    updateImg();
                }}
            />}
            { !verifyImg && <div className={styles.verifyCodeLoading}><Spin /></div> }
            {props.children}
        </>
    </Input>);
});